package com.msdp.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import com.msdp.entity.Message;
import com.msdp.entity.WebSocket;
import com.msdp.service.MessageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @program: tools
 * @Description： 通过这个类进行连接WebSocket的，默认发信息就进入onMessage解析
 */
@Component
@ServerEndpoint(value = "/webSocket/{userId}")
@Slf4j
public class WebSocketUtil {

  /**
   * 登录连接数 应该也是线程安全的
   */
  private static int loginCount = 0;
  /**
   * user 线程安全的
   */
  private static final Map<String, WebSocket> userMap = new ConcurrentHashMap<String, WebSocket>();

  @Autowired
  private  MessageService messageService;

  /**
   * @Description: 收到消息触发事件，这个消息是连接人发送的消息
   * @Param [messageInfo, session]
   * @Return: void { "userId": "test2", "message": "你收到了嘛？这是用户test发的消息！" }
   **/
  @OnMessage
  public void onMessage(String messageInfo, Session session)
      throws IOException, InterruptedException {
    if (StringUtils.isBlank(messageInfo)) {
      return;
    }
    // 当前用户
    String userId = session.getPathParameters().get("userId");
//    Long userId = UserHolder.getUser().getId();
    // JSON数据
    log.info("onMessage:{}", messageInfo);
    Message message = JSONUtil.toBean(messageInfo, Message.class);
    message.setSendUser(Long.valueOf(userId));
    // 插入数据库,保存消息
//    messageService.sendMessage(message);
    Long receiveUser = message.getReceiveUser();
    System.out.println("接收信息:" + messageInfo + "," + receiveUser);
    // 发送给指定用户
    sendMessageTo(messageInfo, receiveUser.toString());
//    sendMessageAll(messageInfo);
    log.info(DateUtil.now() + " | " + receiveUser + " 私人消息-> " + messageInfo, receiveUser);
  }

  /**
   * @Description: 打开连接触发事件
   * @Param [account, session, config]
   * @Return: void
   **/
  @OnOpen
  public void onOpen(@PathParam("userId") String userId, Session session) throws IOException {
    WebSocket webSocket = new WebSocket();
    webSocket.setUserId(userId);
    webSocket.setSession(session);
    boolean containsKey = userMap.containsKey(userId);
    if (!containsKey) {
      // 添加登录用户数量
      addLoginCount();
      userMap.put(userId, webSocket);
    }
    log.info("打开连接触发事件!已连接用户: " + userId);
    log.info("当前在线人数: " + loginCount);
//    Message message = new Message();
//    message.setContent(userId + " 已连接");
//    sendMessageAll(JSONObject.toJSONString(message));
  }

  /**
   * @Description: 关闭连接触发事件
   * @Param [session, closeReason]
   * @Return: void
   **/
  @OnClose
  public void onClose(@PathParam("userId") String userId, Session session,
      CloseReason closeReason) throws IOException {
    boolean containsKey = userMap.containsKey(userId);
    if (containsKey) {
      // 删除map中用户
      userMap.remove(userId);
      // 减少断开连接的用户
      reduceLoginCount();
    }
    log.info("关闭连接触发事件!已断开用户: " + userId);
    log.info("当前在线人数: " + loginCount);
//    Message message = new Message();
//    message.setContent(userId + " 已断开");
//    sendMessageAll(JSONObject.toJSONString(message));
  }

  /**
   * @Description: 传输消息错误触发事件
   * @Param [error ：错误]
   * @Return: void
   **/
  @OnError
  public void onError(Throwable error) {
    log.info("onError:{}", error.getMessage());
  }

  /**
   * @Description: 发送指定用户信息
   * @Param [message：信息, userId：用户]
   * @Return: void
   **/
  public void sendMessageTo(String message, String userId) throws IOException {
    for (WebSocket user : userMap.values()) {
      if (user.getUserId().equals(userId)) {
        System.out.println("用户:" + userId + "收到信息:" + message);
        user.getSession().getAsyncRemote().sendText(message);
      }
    }
  }

  /**
   * @Description: 发给所有人
   * @Param [message：信息]
   * @Return: void
   **/
  public void sendMessageAll(String message) throws IOException {
    for (WebSocket item : userMap.values()) {
      item.getSession().getAsyncRemote().sendText(message);
    }
  }

  /**
   * @Description: 连接登录数增加
   * @Param []
   * @Return: void
   **/
  public static synchronized void addLoginCount() {
    loginCount++;
  }

  /**
   * @Description: 连接登录数减少
   * @Param []
   * @Return: void
   **/
  public static synchronized void reduceLoginCount() {
    loginCount--;
  }

  /**
   * @Description: 获取用户
   * @Param []
   * @Return: java.util.Map<java.lang.String, com.cn.webSocket.WebSocket>
   **/
  public synchronized Map<String, WebSocket> getUsers() {
    return userMap;
  }

}

